package cn.seaboot.admin.mvc;

import cn.seaboot.commons.exception.SystemError;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 方便获取 Spring 上下文的静态工具类。
 * 虽然是静态类，仍然需要注意项目运行生命周期，至少要在对象初始化之后调用。
 * <p>
 * 应用场景：像是 quartz 框架，在 job 实现类中，不方便获取 {@link ApplicationContext}
 *
 * @author Mr.css
 * @version 2020-01-14 15:33
 */
@Configuration
public class SpringContext {
    /**
     * spring application context
     */
    private static ApplicationContext context;

    /**
     * Spring上下文
     */
    @Resource
    private ApplicationContext applicationContext;

    @PostConstruct
    public void init() {
        SpringContext.context = this.applicationContext;
        if (context == null) {
            throw new SystemError("SpringContext.applicationContext is null!");
        }
    }

    /**
     * 获取上下文
     *
     * @return applicationContext
     * @throws SystemError 过早地调用上下文，至少要在对象互相注入之后调用
     */
    public static ApplicationContext getApplicationContext() {
        if (context == null) {
            throw new SystemError("SpringContext.applicationContext is null!");
        }
        return context;
    }

    /**
     * 获取对象
     *
     * @param name 对象name
     * @return 对象
     * @throws SystemError 过早地调用上下文，至少要在对象互相注入之后调用
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 获取对象
     *
     * @param clazz 对象clazz
     * @return 对象
     * @throws SystemError 过早地调用上下文，至少要在对象互相注入之后调用
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 获取对象
     *
     * @param clazz 对象clazz
     * @param name  对象name
     * @return 对象
     * @throws SystemError 过早地调用上下文，至少要在对象互相注入之后调用
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}